﻿using jvm.instructions.common;
using jvm.rtda;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace jvm.instructions.loads
{
    class XAStoreUtil
    {
        public static void CheckNotNull(JObject obj)
        {
            if (obj == null)
            {
                Console.WriteLine("java.lang.NullPointerException");
                Environment.Exit(0);
            }
        }

        public static void CheckIndex(int index, int arrayLength)
        {
            if (index < 0 || index >= arrayLength)
            {
                Console.WriteLine("java.lang.IndexOutOfBoundsException");
                Environment.Exit(0);
            }
        }
    }

    class AASTORE : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            JObject obj = frame.operandStack.PopRef();
            int index = frame.operandStack.PopInt();
            JObject array = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(array);
            JObject[] refs = array.Refs();
            XALoadUtil.CheckIndex(index, refs.Length);
            refs[index] = obj;
        }
    }

    class BASTORE : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int obj = frame.operandStack.PopInt();
            int index = frame.operandStack.PopInt();
            JObject array = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(array);
            byte[] refs = array.Bytes();
            XALoadUtil.CheckIndex(index, refs.Length);
            refs[index] = (byte)obj;
        }
    }

    class CASTORE : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int obj = frame.operandStack.PopInt();
            int index = frame.operandStack.PopInt();
            JObject array = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(array);
            char[] refs = array.Chars();
            XALoadUtil.CheckIndex(index, refs.Length);
            refs[index] = (char)obj;
        }
    }

    class SASTORE : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int obj = frame.operandStack.PopInt();
            int index = frame.operandStack.PopInt();
            JObject array = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(array);
            short[] refs = array.Shorts();
            XALoadUtil.CheckIndex(index, refs.Length);
            refs[index] = (short)obj;
        }
    }

    class IASTORE : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int obj = frame.operandStack.PopInt();
            int index = frame.operandStack.PopInt();
            JObject array = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(array);
            int[] refs = array.Ints();
            XALoadUtil.CheckIndex(index, refs.Length);
            refs[index] = obj;
        }
    }

    class LASTORE : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            long obj = frame.operandStack.PopLong();
            int index = frame.operandStack.PopInt();
            JObject array = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(array);
            long[] refs = array.Longs();
            XALoadUtil.CheckIndex(index, refs.Length);
            refs[index] = obj;
        }
    }

    class FASTORE : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            float obj = frame.operandStack.PopFloat();
            int index = frame.operandStack.PopInt();
            JObject array = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(array);
            float[] refs = array.Floats();
            XALoadUtil.CheckIndex(index, refs.Length);
            refs[index] = obj;
        }
    }

    class DASTORE : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            double obj = frame.operandStack.PopDouble();
            int index = frame.operandStack.PopInt();
            JObject array = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(array);
            double[] refs = array.Doubles();
            XALoadUtil.CheckIndex(index, refs.Length);
            refs[index] = obj;
        }
    }
}
